package cn.epsilon3.utils;

import cn.epsilon3.constant.Base;
import cn.epsilon3.exception.Epsilon3Exception;
import org.apache.commons.codec.binary.Base32;
import org.apache.commons.codec.binary.Hex;

import java.net.URLEncoder;
import java.security.SecureRandom;

/**
 * Authenticator utility class
 * Contains generated keys, dynamic code，and the URI string of the TOTP key
 *
 * @author: epsilon3
 * @date: 2023/8/21 13:53
 */
public class AuthenticatorUtils {

	/**
	 * generate a random key
	 *
	 * @return key string
	 */
	public static String generateRandomKey() {
	    SecureRandom random = new SecureRandom();
	    byte[] bytes = new byte[20];
	    random.nextBytes(bytes);
	    Base32 base32 = new Base32();
	    return base32.encodeToString(bytes).toLowerCase();
	}


	/**
	 * generate dynamic code
	 * change the code once in 30s
	 *
	 * @param key
	 *
	 * @return dynamic code
	 */
	public static String generateCode(String key) {
	    Base32 base32 = new Base32();
	    byte[] bytes = base32.decode(key);
	    String hexKey = Hex.encodeHexString(bytes);
	    long time = (System.currentTimeMillis() / 1000) / 30;
	    String hexTime = Long.toHexString(time);
	    return TOTPUtils.generateTOTP(hexKey, hexTime, "6");
	}

	/**
	 * generate URI string of the TOTP key
	 *
	 * @param secretKey
	 * @param account
	 * @param issuer
	 *
	 * @return URI string
	 */
	public static String generateAuthenticatorCode(String secretKey, String account, String issuer) {
	    try {
			StringBuilder sb = new StringBuilder();
			sb.append("otpauth://totp/")
					.append(URLEncoder.encode(issuer + ":" + account, Base.ENCODE_UTF8))
					.append("?secret=")
					.append(URLEncoder.encode(secretKey, Base.ENCODE_UTF8))
					.append("&issuer=")
					.append(URLEncoder.encode(issuer, Base.ENCODE_UTF8));
			String uri = sb.toString();
			String encodeUri = uri.replace("+", "%20");
			return encodeUri;
	    } catch (Exception e) {
	        throw new Epsilon3Exception("generate URI string exception" + e.getMessage());
	    }
	}
}
